'    Copyright 2008 Jan Molnar <jan.molnar@abds.de>
'
'    This file is part of JCQ.

'    JCQ is free software: you can redistribute it and/or modify
'    it under the terms of the GNU General Public License as published by
'    the Free Software Foundation, either version 2 of the License, or
'    (at your option) any later version.

'    JCQ is distributed in the hope that it will be useful,
'    but WITHOUT ANY WARRANTY; without even the implied warranty of
'    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
'    GNU General Public License for more details.

'    You should have received a copy of the GNU General Public License
'    along with JCQ. If not, see <http://www.gnu.org/licenses/>.


Imports System.Windows
Imports System.Windows.Interop
Imports System.Runtime.InteropServices

Partial Public Class WindowResizeExtender
    ' This partial class contains all API related code.

    Private _Handle As IntPtr
    Private _Source As HwndSource
    Private _InteropHelper As WindowInteropHelper

    Protected Sub WindowSourceInitialized(ByVal sender As Object, ByVal e As System.EventArgs) Handles _Window.SourceInitialized
        Dim wnd As Window

        wnd = DirectCast(sender, Window)

        ' Create a helper object to gain access to the Win32 handle
        _InteropHelper = New WindowInteropHelper(wnd)

        _Handle = _InteropHelper.Handle
        _Source = HwndSource.FromHwnd(_Handle)

        ' Add a hook to process window messages
        _Source.AddHook(New HwndSourceHook(AddressOf WndProc))
    End Sub

    Private Function WndProc(ByVal hwnd As IntPtr, ByVal msg As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr, ByRef handled As Boolean) As IntPtr
        Dim wmsg As WindowMessage

        'TODO: process window messages here
        wmsg = DirectCast(msg, WindowMessage)

        Select Case wmsg
            Case WindowMessage.WM_GETMINMAXINFO
                ' Enable Max/Min Size support.

                Dim minmax As New MinMaxInfo
                Dim trans As Media.Matrix
                Dim maxSize As Point
                Dim minSize As Point
                Dim workArea As Point

                trans = _Source.CompositionTarget.TransformToDevice

                Marshal.PtrToStructure(lParam, minmax)

                workArea = trans.Transform(New Point(SystemParameters.WorkArea.Width, SystemParameters.WorkArea.Height))

                minmax.ptMaxSize.x = CInt(workArea.X)
                minmax.ptMaxSize.y = CInt(workArea.Y)

                maxSize = trans.Transform(New Point(_Window.MaxWidth, _Window.MaxHeight))

                If _Window.MaxWidth < Double.PositiveInfinity Then minmax.ptMaxTrackSize.x = CInt(maxSize.X)
                If _Window.MaxHeight < Double.PositiveInfinity Then minmax.ptMaxTrackSize.y = CInt(maxSize.Y)

                minSize = trans.Transform(New Point(_Window.MinWidth, _Window.MinHeight))

                If _Window.MinWidth > 0 Then minmax.ptMinTrackSize.x = CInt(minSize.X)
                If _Window.MinHeight > 0 Then minmax.ptMinTrackSize.y = CInt(minSize.Y)

                Marshal.StructureToPtr(minmax, lParam, True)

                handled = True
            Case WindowMessage.WM_SIZING
                Dim r As Win32Rect = New Win32Rect

                System.Runtime.InteropServices.Marshal.PtrToStructure(lParam, r)

                handled = WmValidateSize(msg, r)

                System.Runtime.InteropServices.Marshal.StructureToPtr(r, lParam, True)

                handled = True
        End Select

        Return IntPtr.Zero
    End Function

    Private Function WmValidateSize(ByVal sizeMode As Integer, ByVal rectangle As Win32Rect) As Boolean
        Dim cx As Integer
        Dim cy As Integer

        cx = rectangle.right - rectangle.left
        cy = rectangle.bottom - rectangle.top

        If cx > SystemParameters.WorkArea.Width Then rectangle.right = CInt(rectangle.left + SystemParameters.WorkArea.Width)
        If cy > SystemParameters.WorkArea.Height Then rectangle.bottom = CInt(rectangle.top + SystemParameters.WorkArea.Height)

        Return True
    End Function
End Class
